/**
 * Copyright (c) Software Institute of PKU
 * All rights reserved. 
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 */
package edu.pku.sei.modeler.editparts;

import java.beans.PropertyChangeEvent;
import java.util.Iterator;

import org.eclipse.draw2d.ChopboxAnchor;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.EllipseAnchor;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.DirectEditPolicy;
import org.eclipse.gef.requests.DirectEditRequest;

import edu.pku.sei.modeler.editpolicies.UMLDiagramGraphicalNodeEditPolicy;
import edu.pku.sei.modeler.figures.ImplementInterfaceFigure;
import edu.pku.sei.modeler.figures.UMLClassFigure;
import edu.pku.sei.modeler.figures.UseInterfaceFigure;
import edu.pku.sei.modeler.model.structure.MetaBendPoint;
import edu.pku.sei.modeler.model.structure.MetaLink;
import edu.pku.sei.modeler.model.structure.MetaNode;
import edu.pku.sei.modeler.model.structure.MetaShapeElement;
import edu.pku.sei.modeler.model.uml.Interfaces.Interface;
import edu.pku.sei.modeler.model.uml.Kernel.Operation;
import edu.pku.sei.modeler.model.uml.Kernel.Property;
import edu.pku.sei.modeler.uml.ResourceFactory;
import edu.pku.sei.modeler.uml.commands.ChangeNameCommand;
import edu.pku.sei.modeler.uml.modelHelper.ModelPackage;

/**
 * @generated
 * 
 */
public class InterfaceEditpart extends AbstractUMLNodeEditPart {
	public InterfaceEditpart(MetaShapeElement model) {
		super(model);
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
	 */
	protected IFigure createFigure() {
		if (getModelElement().getType() == Interface.TYPE_USEINTERFACE) {
			return new UseInterfaceFigure();
		} else if (getModelElement().getType() == Interface.TYPE_IMPLEMENTINTERFACE
				|| getModelElement().getType() == Interface.TYPE_COMPONENTINTERFACE) {
			ImplementInterfaceFigure figure = new ImplementInterfaceFigure();
			figure.setName(getModelElement().getName());
			return figure;
		} else {
			Label header = new Label("<<interface>>");
			header.setFont(ResourceFactory.getTextFont());
			header.setForegroundColor(ColorConstants.black);
			UMLClassFigure figure = new UMLClassFigure(header);
			figure.getNameLabel().setFont(ResourceFactory.getHeadItalicsFont());
			return figure;
		}
	}

	protected DirectEditPolicy createDirectEditPolicy() {
		return new DirectEditPolicy() {
			protected Command getDirectEditCommand(DirectEditRequest request) {
				return new ChangeNameCommand(getModelElement(),
						(String) request.getCellEditor().getValue());
			}

			protected void showCurrentEditValue(DirectEditRequest request) {
				IFigure fig = getDirectEditFigure();
				if (fig instanceof Label) {
					((Label) fig).setText(getModelElement().getName());
					fig.getUpdateManager().performUpdate();
				}
			}
		};
	}

	@Override
	protected IFigure getDirectEditFigure() {
		if (this.getModelElement().getType() == Interface.TYPE_IMPLEMENTINTERFACE) {
			return ((ImplementInterfaceFigure) this.getFigure()).getNameLabel();
		}
		return ((UMLClassFigure) this.getFigure()).getNameLabel();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
	 */
	protected void createEditPolicies() {
		super.createEditPolicies();
	}

	protected void handlePropertyChanged(PropertyChangeEvent event) {
		refreshVisuals();
		super.handlePropertyChanged(event);
	}

	private Interface getModelElement() {
		return (Interface) ((MetaNode) getModel()).getModelElement();
	}

	protected void refreshVisuals() {
		Interface interfaceElement = getModelElement();
		if (interfaceElement.getType() == Interface.TYPE_INTERFACE) {
			super.refreshVisuals();
			UMLClassFigure interfaceFigure = (UMLClassFigure) this.getFigure();
			// ActionHandleManager actionMngr = new ActionHandleManager(this);
			//
			// PaletteDrawer entries = new PaletteDrawer("creation tool");
			// try {
			//
			// AbstractFactory modelFactory =
			// ModelRegistry.getRegistry().getFactory
			// (this.getNode().getModel());
			//
			// StructureFactory sFactory = (StructureFactory)
			// ModelRegistry.getRegistry
			// ().getStructureFactory(this.getNode().getModel());
			//
			// CreationToolEntry propertyToolEntry = new
			// CreationToolEntry(ImageProvider.PROPERTY_IMAGE,
			// "Add New Property", new MetaCreationFactory(true,
			// ModelPackage.__PROPERTY__, modelFactory, sFactory),
			// ImageProvider.getImageDescriptor(ImageProvider.PROPERTY_IMAGE),
			// null);
			//
			// CreationToolEntry operationToolEntry = new
			// CreationToolEntry(ImageProvider.OPERATION_IMAGE,
			// "Add New Operation", new MetaCreationFactory(
			// true, ModelPackage.__OPERATION__, modelFactory, sFactory),
			// ImageProvider
			// .getImageDescriptor(ImageProvider.OPERATION_IMAGE), null);
			//
			// entries.add(propertyToolEntry);
			// entries.add(operationToolEntry);
			// actionMngr.addTool(entries, PositionConstants.SOUTH_EAST);
			//
			// } catch (Exception e) {
			// e.printStackTrace();
			// }

			// refresh class name
			refreshInterfaceName(interfaceElement, interfaceFigure);

			// refresh attributes
			refreshAttributes(interfaceElement, interfaceFigure);

			// refresh operations
			refreshOperations(interfaceElement, interfaceFigure);
		} else if (interfaceElement.getType() == Interface.TYPE_USEINTERFACE) {
			UseInterfaceFigure figure = (UseInterfaceFigure) this.getFigure();
			// super.refreshVisuals();
			Rectangle constraint = new Rectangle(0, 0, -1, -1);
			MetaNode node = getNode();
			Point p = new Point(node.getLocationX(), node.getLocationY());
			constraint.setLocation(p);
			constraint.width = 24;
			constraint.height = 24;
			((GraphicalEditPart) getParent()).setLayoutConstraint(this,
					getFigure(), constraint);

			if (node.getIncomings().size() > 0) {
				MetaLink link = ((MetaLink) node.getIncomings().get(0));
				if (link.getBendPoints().size() != 0) {
					MetaBendPoint bp = (MetaBendPoint) link.getBendPoints()
							.get(link.getBendPoints().size() - 1);
					figure.setLocation(new Point(bp.x, bp.y), new Point(node
							.getLocationX(), node.getLocationY()));
				} else {
					MetaNode source = ((MetaLink) node.getIncomings().get(0))
							.getSource();
					figure.setLocation(new Point(source.getLocationX()
							+ source.getWidth() / 2, source.getLocationY()
							+ source.getHeight() / 2), new Point(node
							.getLocationX(), node.getLocationY()));
				}
				figure.repaint();
			}
		} else if (interfaceElement.getType() == Interface.TYPE_IMPLEMENTINTERFACE) {
			ImplementInterfaceFigure figure = (ImplementInterfaceFigure) this
					.getFigure();
			figure.getNameLabel().setText("" + interfaceElement.getName());
			super.refreshVisuals();
			Rectangle constraint = new Rectangle(0, 0, -1, -1);
			MetaNode node = getNode();
			Point p = new Point(node.getLocationX(), node.getLocationY());
			constraint.setLocation(p);
			((GraphicalEditPart) getParent()).setLayoutConstraint(this,
					getFigure(), constraint);
		} else if (interfaceElement.getType() == Interface.TYPE_COMPONENTINTERFACE) {
			ImplementInterfaceFigure figure = (ImplementInterfaceFigure) this
					.getFigure();
			figure.getNameLabel().setText("" + interfaceElement.getName());
			super.refreshVisuals();
			Rectangle constraint = new Rectangle(0, 0, -1, -1);
			MetaNode node = getNode();
			Point p = new Point(node.getLocationX(), node.getLocationY());
			constraint.setLocation(p);
			constraint.width = 20;
			constraint.height = 20;
			((GraphicalEditPart) getParent()).setLayoutConstraint(this,
					getFigure(), constraint);
		}

	}

	private void refreshOperations(Interface modelElement,
			UMLClassFigure interfaceFigure) {
		Figure operationFigure = interfaceFigure.getOpCompart();
		operationFigure.removeAll();

		for (Iterator iter = modelElement.getOwnedOperation().iterator(); iter
				.hasNext();) {
			Label operation = this.getOperationFigure((Operation) iter.next());
			operation.setForegroundColor(ColorConstants.black);
			operationFigure.add(operation);
		}
	}

	private Label getAttributeFigure(final Property utilProperty) {
		Label nameLabelForOneAttribute = new Label();
		String newText = utilProperty.getCustomLabel();
		nameLabelForOneAttribute.setText(newText);
		nameLabelForOneAttribute.setFont(ResourceFactory.getTextFont());
		nameLabelForOneAttribute.setLabelAlignment(PositionConstants.LEFT);
		return nameLabelForOneAttribute;
	}

	public Label getOperationFigure(final Operation utilOperation) {
		Label operationFigure = new Label();
		String newText = utilOperation.getCustomLabel();
		operationFigure.setFont(ResourceFactory.getTextFont());
		operationFigure.setLabelAlignment(PositionConstants.LEFT);
		operationFigure.setText(newText);
		return operationFigure;
	}

	private void refreshInterfaceName(Interface modelElement,
			UMLClassFigure interfaceFigure) {
		String interfaceName = modelElement.getName();
		Label nameLabel = interfaceFigure.getNameLabel();
		nameLabel.setText(interfaceName);
		//nameLabel.setIcon(ImageProvider.getImage(ImageProvider.INTERFACE_IMAGE
		// ));
		// nameLabel.setIconAlignment(PositionConstants.TOP);
		nameLabel.setTextAlignment(PositionConstants.CENTER);
	}

	protected void refreshAttributes(Interface modelElement,
			UMLClassFigure interfaceFigure) {
		// MetaClassFigure fig = (MetaClassFigure)this.getFigure();
		Figure attributeContainer = interfaceFigure.getAttrCompart();
		attributeContainer.removeAll();
		if (modelElement.getOwnedAttribute().size() == 0) {
			attributeContainer.setVisible(false);
		} else {
			attributeContainer.setVisible(true);
			for (Iterator iter = modelElement.getOwnedAttribute().iterator(); iter
					.hasNext();) {
				Label attribute = this.getAttributeFigure((Property) iter
						.next());
				attribute.setForegroundColor(ColorConstants.black);
				attributeContainer.add(attribute);

			}
		}
	}
	
	public ConnectionAnchor getSourceConnectionAnchor(
			ConnectionEditPart connection) {
		if (getModelElement().getType() == Interface.TYPE_IMPLEMENTINTERFACE) {
			if (anchor == null)
				anchor = new EllipseAnchor(((ImplementInterfaceFigure)getFigure()).getRoot());
			return anchor;			
		} else {
			return super.getSourceConnectionAnchor(connection);
		}
	}

	public ConnectionAnchor getSourceConnectionAnchor(Request request) {
		if (getModelElement().getType() == Interface.TYPE_IMPLEMENTINTERFACE) {
			if (anchor == null)
				anchor = new EllipseAnchor(((ImplementInterfaceFigure)getFigure()).getRoot());
			return anchor;
		} else {
			return super.getSourceConnectionAnchor(request);
		}
	}

	public ConnectionAnchor getTargetConnectionAnchor(
			ConnectionEditPart connection) {
		if (getModelElement().getType() == Interface.TYPE_IMPLEMENTINTERFACE) {			
			if (anchor == null)
				anchor = new EllipseAnchor(((ImplementInterfaceFigure)getFigure()).getRoot());
			return anchor;
		} else {
			return super.getTargetConnectionAnchor(connection);
		}
	}

	public ConnectionAnchor getTargetConnectionAnchor(Request request) {
		if (getModelElement().getType() == Interface.TYPE_IMPLEMENTINTERFACE) {			
			if (anchor == null)
				anchor = new EllipseAnchor(((ImplementInterfaceFigure)getFigure()).getRoot());
			return anchor;
		} else {
			return super.getTargetConnectionAnchor(request);
		}
	}
}
